//==============================================================================
// dbb string inline file
//==============================================================================

//------------------------------------------------------------------------
char*
String::Rep::getData()
{
	return reinterpret_cast<char*>(this+1);
}

//------------------------------------------------------------------------
const char*
String::Rep::getData() const
{
	return reinterpret_cast<const char*>(this+1);
}

//------------------------------------------------------------------------
char*
String::Rep::refCopy()
{
	++m_references;
	return getData();
}

//------------------------------------------------------------------------
dbbsize
String::Rep::getSize() const
{
	return sizeof(Rep) + m_capacity + 1;
}

//------------------------------------------------------------------------
void
String::Rep::unRef()
{
	if(--m_references<0)
	{
		freeMemory();
	}
}

//------------------------------------------------------------------------
inline
String::String(Rep* r)
:m_string(r->getData())
{

}

//------------------------------------------------------------------------
inline String::Rep&
String::_getRep() const
{
	return *(reinterpret_cast<Rep*>(m_string)-1);
}

//------------------------------------------------------------------------
inline String::Rep&
String::_GetEmptyStringRep()
{
	return *reinterpret_cast<Rep*>(s_emptyStringRep);
}

//------------------------------------------------------------------------
inline dbbsize
String::getLength() const
{
	return _getRep().m_length;
}

//------------------------------------------------------------------------
inline
String::String()
{
	m_string = _GetEmptyStringRep().refCopy();
}

//------------------------------------------------------------------------
inline
String::String(const String& other)
{
	m_string = other._getRep().refCopy();
}

//------------------------------------------------------------------------
inline
String::String(const char* s)
{
	if(DBBNULL!=s)
	{
		dbbsize slen = StrLen(s);
		m_string = Rep::Create(slen)->getData();
		String::MemCpy(m_string,s,slen+1);
	}
	else
	{
		m_string = _GetEmptyStringRep().refCopy();
	}
}

//------------------------------------------------------------------------
inline
String::String(const char* buf, dbbsize len)
{
	dbbassert(len>=0);
	m_string = Rep::Create(len)->getData();
	String::MemCpy(m_string,buf,len);
	m_string[len] = 0;
}

//------------------------------------------------------------------------
inline void
String::operator =(const String& s)
{
	char* newStr = s._getRep().refCopy();
	_getRep().unRef();
	m_string = newStr;
}

//------------------------------------------------------------------------
inline void
String::operator =(const char* s)
{
	if(DBBNULL!=s&&0!=*s)
	{
		dbbsize slen = StrLen(s);
		if(_getRep().m_capacity<slen||_getRep().m_references>0)
		{
			_getRep().unRef();
			m_string = Rep::Create(slen)->getData();
		}
		String::MemCpy(m_string,s,slen+1);
		_getRep().m_length = slen;
	}
	else
	{
		_getRep().unRef();
		m_string = _GetEmptyStringRep().refCopy();
	}
}

//------------------------------------------------------------------------
inline
String::~String()
{
	_getRep().unRef();
}

//------------------------------------------------------------------------
inline char
String::operator [](dbbindex i) const
{
	return m_string[i];
}

//------------------------------------------------------------------------
inline const char*
String::cString() const
{
	return m_string;
}

//------------------------------------------------------------------------
inline int
String::compareTo(const String& other) const
{
	return StrCmp(cString(),other.cString());
}

//------------------------------------------------------------------------
inline int
String::compareTo(const char *other) const
{
	return StrCmp(cString(),other);
}

//------------------------------------------------------------------------
inline int
String::compareToIgnoreCase(const String& other) const
{
	return StrCasecmp(cString(),other.cString());
}

//------------------------------------------------------------------------
inline int
String::compareToIgnoreCase(const char *other) const
{
	return StrCasecmp(cString(),other);
}

//------------------------------------------------------------------------
inline bool
operator< (const String& lhs, const String& rhs)
{
	return lhs.compareTo(rhs)<0;
}

//------------------------------------------------------------------------
inline bool
operator> (const String& lhs, const String& rhs)
{
	return lhs.compareTo(rhs)>0;
}

//------------------------------------------------------------------------
inline bool
operator==(const String& lhs, const String& rhs)
{
	return lhs.compareTo(rhs)==0;
}

//------------------------------------------------------------------------
inline bool
operator!=(const String& lhs, const String& rhs)
{
	return lhs.compareTo(rhs)!=0;
}

//------------------------------------------------------------------------
inline bool
operator==(const String& lhs, const char* rhs)
{
	return String::StrCmp(lhs.cString(),rhs)==0;
}

//------------------------------------------------------------------------
inline bool
operator==(const char* lhs, const String& rhs)
{
	return String::StrCmp(lhs,rhs.cString())==0;
}

//------------------------------------------------------------------------
inline bool
operator!=(const String& lhs, const char* rhs)
{
	return String::StrCmp(lhs.cString(),rhs)!=0;
}

//------------------------------------------------------------------------
inline bool
operator!=(const char* lhs, const String& rhs)
{
	return String::StrCmp(lhs,rhs.cString())!=0;
}
